﻿using DocumentFormat.OpenXml.ExtendedProperties;
using ExCSS;
using LunarSF.SHomeWorkshop.LunarMarkdownEditor.Utils.NPOIHelp;
using OneOf.Types;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Printing;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Documents.Serialization;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor.Utils
{
    public class 报表文件生成器
    {
        public static void 生成单页报表文件(string filePath)
        {
            // 创建 XPS 文档
            using (XpsDocument xpsDoc = new XpsDocument(
                filePath,
                System.IO.FileAccess.ReadWrite,
                CompressionOption.Maximum))
            {
                // 获取文档写入器
                XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDoc);

                // 创建页面内容
                FixedPage page = 创建报表页面();

                // 直接写入页面
                writer.Write(page);
            }
        }

        private static FixedPage 创建报表页面()
        {
            FixedPage page = new FixedPage
            {
                Width = 96 * 8.5,  // 8.5英寸
                Height = 96 * 11,   // 11英寸
                Background = Brushes.White
            };

            // 添加内容
            TextBlock text = new TextBlock
            {
                Text = "直接生成的XPS文档",
                FontSize = 24,
                Margin = new Thickness(100)
            };
            FixedPage.SetLeft(text, 100);
            FixedPage.SetTop(text, 200);
            page.Children.Add(text);

            // 添加图像
            Image image = new Image
            {
                Source = new BitmapImage(new Uri("C:\\path\\to\\image.png")),
                Width = 200,
                Height = 100
            };
            FixedPage.SetLeft(image, 100);
            FixedPage.SetTop(image, 300);
            page.Children.Add(image);

            return page;
        }

        public static 文件 生成多页报表文件(string reportScript, string textOf2DTable, string filePath)
        {
            if (File.Exists(filePath))
            {
                var answer = LMessageBox.ShowQuestion("指定路径已存在同名文件。要覆盖吗？");
                if (answer != MessageBoxResult.Yes) return new 文件(filePath);
                else
                {
                    try
                    {
                        File.Delete(filePath);
                    }
                    catch (Exception ex)
                    {
                        LMessageBox.ShowWarning(ex.Message);
                        return new 文件(filePath);
                    }
                }
            }

            try
            {
                var fi = new FileInfo(filePath);

                var dataTable = new 文字表(textOf2DTable);

                if (string.IsNullOrWhiteSpace(reportScript))
                {
                    LMessageBox.ShowWarning("报表生成脚本为空字符串或只含空白字符。");
                    return new 文件(filePath);
                }

                if (dataTable == null)
                {
                    LMessageBox.ShowWarning("未提供作为填充数据源的文字表对象。");
                    return new 文件(filePath);
                }

                if (dataTable.文字表头行集 == null || dataTable.文字表头行集.Count < 1)
                {
                    LMessageBox.ShowWarning("用作数据源的文字表没有字段名行（表头行）。");
                    return new 文件(filePath);
                }

                if (dataTable.文字表体行集 == null || dataTable.文字表体行集.Count < 1)
                {
                    LMessageBox.ShowWarning("用作数据源的文字表没有记录行（表体行）。");
                    return new 文件(filePath);
                }

                var warningMsg = new StringBuilder();

                var result = 生成多页报表文件(reportScript, dataTable, ref warningMsg, fi);
                if (string.IsNullOrEmpty(result) != true)
                {
                    LMessageBox.ShowWarning(result);
                }

                if (warningMsg.Length > 0)
                {
                    LMessageBox.ShowWarning(warningMsg.ToString());
                }
                return new 文件(filePath);
            }
            catch (Exception ex)
            {
                LMessageBox.ShowWarning(ex.Message);
                return new 文件(filePath);
            }
        }

        /// <summary>
        /// 每记录生成一个 XPS 报表文件。
        /// </summary>
        /// <param name="reportScript">报表生成脚本。</param>
        /// <param name="textOf2DTable">二维文字表，每行记录一个 XPS 文件。</param>
        /// <param name="baseFilePath">基准文件名。如果 fieldNamesAsShortFileNames 为空，只取路径使用；如 fieldNamesAsShortFileNames 不为空，则按 fieldNamesAsShortFileNames 取字段值拼接成文件短名。</param>
        /// <param name="fieldNamesAsShortFileNames"></param>
        /// <returns></returns>
        public static IronPython.Runtime.PythonList 逐记录生成报表文件(string reportScript, string textOf2DTable, string baseFilePath, IronPython.Runtime.PythonList fieldNamesAsShortFileNames)
        {
            try
            {
                var fi = new FileInfo(baseFilePath);
                var di = fi.Directory;

                if (di.Exists == false)
                {
                    di.Create();
                }

                var files = di.GetFiles();
                if (files != null && files.Length > 0)
                {
                    var answer = LMessageBox.ShowQuestion("指定文件路径所在目录不为空，继续执行操作会覆盖现有同名文件。\r\n　　要继续吗？");
                    if (answer != MessageBoxResult.Yes) return null;
                }

                var dataTable = new 文字表(textOf2DTable);

                if (string.IsNullOrWhiteSpace(reportScript))
                {
                    LMessageBox.ShowWarning("报表生成脚本为空字符串或只含空白字符。");
                    return null;
                }

                if (dataTable == null)
                {
                    LMessageBox.ShowWarning("未提供作为填充数据源的文字表对象。");
                    return null;
                }

                if (dataTable.文字表头行集 == null || dataTable.文字表头行集.Count < 1)
                {
                    LMessageBox.ShowWarning("用作数据源的文字表没有字段名行（表头行）。");
                    return null;
                }

                if (dataTable.文字表体行集 == null || dataTable.文字表体行集.Count < 1)
                {
                    LMessageBox.ShowWarning("用作数据源的文字表没有记录行（表体行）。");
                    return null;
                }

                var warningMsg = new StringBuilder();
                var fileList = new IronPython.Runtime.PythonList();

                var markLength = dataTable.文字表体行集.Count.ToString().Length + 1;

                for (int i = 0; i < dataTable.文字表体行集.Count; i++)
                {
                    var recordTextTable = dataTable.记录行到文字表(i);

                    string subFilePath;
                    if (fieldNamesAsShortFileNames == null || fieldNamesAsShortFileNames.Count <= 0)
                    {
                        subFilePath = Path.Combine(fi.Directory.FullName, fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length) + "_" + i.ToString(markLength.ToString()));
                    }
                    else
                    {
                        // 按字段取值，拼合文件名。
                        var shortName = new StringBuilder();
                        foreach (var fieldName in fieldNamesAsShortFileNames)
                        {
                            var fieldNameIndex = -1;
                            for (int fieldIndex = 0; fieldIndex < recordTextTable.文字表头行集[0].行内总单元格数; fieldIndex++)
                            {
                                if (recordTextTable.文字表头行集[0].文字表单元格集[fieldIndex].文字表单元格文本.ToLower() == fieldName.ToString())
                                {
                                    fieldNameIndex = fieldIndex;
                                    break;
                                }
                            }
                            var fieldValue = recordTextTable.文字表体行集[0].文字表单元格集[fieldNameIndex].文字表单元格文本;
                            if (string.IsNullOrWhiteSpace(fieldValue) == false)
                            {
                                shortName.Append(fieldValue);
                                shortName.Append("-");
                            }
                        }

                        if (shortName.Length <= 0)
                        {
                            subFilePath = Path.Combine(fi.Directory.FullName, fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length) + "_" + i.ToString(markLength.ToString()) + ".xps");
                        }
                        else
                        {
                            string shortFileName;
                            if (shortName[shortName.Length - 1] == '-')
                            {
                                shortFileName = shortName.ToString(0, shortName.Length - 1);
                            }
                            else
                            {
                                shortFileName = shortName.ToString();
                            }

                            // 仍有可能为空字符串（例如字段值就是一个 - 的情况）
                            if (string.IsNullOrEmpty(shortFileName))
                            {
                                subFilePath = Path.Combine(fi.Directory.FullName, fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length) + "_" + i.ToString(markLength.ToString()) + ".xps");
                            }
                            else
                            {
                                subFilePath = Path.Combine(fi.Directory.FullName, shortFileName + ".xps");
                            }
                        }
                    }

                    var result = 生成多页报表文件(reportScript, dataTable.记录行到文字表(i), ref warningMsg, new FileInfo(subFilePath));
                    if (string.IsNullOrEmpty(result) != true)
                    {
                        warningMsg.AppendLine(result);
                    }
                    else
                    {
                        fileList.Add(new 文件(subFilePath));
                    }
                }

                if (warningMsg.Length > 0)
                {
                    LMessageBox.ShowWarning(warningMsg.ToString());
                }
                return fileList;
            }
            catch (Exception ex)
            {
                LMessageBox.ShowWarning(ex.Message);
                return null;
            }
        }

        private static string 生成多页报表文件(string reportScript, NPOIHelp.文字表 dataTable, ref StringBuilder warningMsg, FileInfo fi)
        {
            var innerWarningMsg = new StringBuilder();

            try
            {
                // 在后台线程执行（需配置为STA）
                Thread thread = new Thread(() =>
                {
                    using (XpsDocument xpsDoc = new XpsDocument(fi.FullName, System.IO.FileAccess.Write))
                    {
                        XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDoc);

                        // 根据数据记录行数，决定添加多少个页面组（因为一行记录可能分散在多个报表页面中）
                        // 每个页面组都会返回一个 List<IFieldUIElement> 列表

                        var fixedDocument = new FixedDocument();
                        var rowsCount = dataTable.文字表体行集.Count;
                        for (int rowIndex = 0; rowIndex < rowsCount; rowIndex++)
                        {
                            var tableBodyRow = dataTable.文字表体行集[rowIndex];
                            var fieldUiElements = 生成页面组(rowIndex, rowsCount,  fixedDocument, reportScript, ref innerWarningMsg, out string defaultImagesPath, out string defaultFieldImagesPath, out System.Windows.Media.Brush errForeColor);

                            // 填充记录
                            填充记录行(dataTable, rowIndex, fieldUiElements, defaultImagesPath, defaultFieldImagesPath, errForeColor);
                        }

                        writer.Write(fixedDocument);
                    }
                });

                thread.SetApartmentState(ApartmentState.STA); // 必须设置为STA线程
                thread.Start();
                thread.Join(); // 等待完成
                return string.Empty;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        /// <summary>
        /// 当使用多个页面填充多条记录时，由于一条记录的字段可能分散在多个报表页面中，所以每条记录对应一个页面组（每页面组中至少有一个报表页面）。
        /// </summary>
        /// <param name="reportScript"></param>
        /// <param name="drawAssistLines"></param>
        /// <param name="warningMsg"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static List<IFieldUIElement> 生成页面组(int groupIndex,    // group 是指报表模板中所有页面组成的一个 Group；groupIndex 是为了计算页码。
                                                       int rowsCount,     // rowsCount 是填充的记录的数量为了计算所有页面的数量
                                                       FixedDocument fixedDocument, 
                                                       string reportScript,
                                                       ref StringBuilder warningMsg,
                                                       out string defaultImagesPath,
                                                       out string defaultFieldImagesPath,
                                                       out System.Windows.Media.Brush errForeColor)
        {
            var rd = new ReporterDefinition(reportScript);
            
            try
            {
                rd.BuildReportModel();
            }
            catch (Exception ex)
            {
                warningMsg.AppendLine(ex.Message);
                errForeColor = null;
                defaultImagesPath = null;
                defaultFieldImagesPath = null;
                return null;
            }

            if (rd.Pages.Count <= 0)
            {
                warningMsg.AppendLine("报表生成脚本中没有定义页面。");
                errForeColor = null;
                defaultImagesPath = null;
                defaultFieldImagesPath = null;
                return null;
            }

            var drawAssistLines = false;     // 直接生成 XPS 报表时默认不绘制辅助线——用这个功能通过脚本生成的情况下，一般都比较讲究，不会直接使用辅助线代替网格线。
            if (rd.AssistLinesVisible != null && rd.AssistLinesVisible.HasValue)
            {
                // 用户设置了“显示辅助线”命令
                // 此时以用户设置为准，忽略界面设置

                drawAssistLines = rd.AssistLinesVisible.Value;
                // ckxPreviewWithAssistLines.IsChecked = drawAssistLines;  // 直接生成XPS文件，不需要更新界面复选框勾选状态
            }
            //else{...}  不变，以传入的参数值（通常就是界面上“预览时显示辅助线”复选框的勾选状态）为准。

            var innerWarningMsg = new StringBuilder();

            var defaultImagesPathInfo = new DirectoryInfo(rd.DefaultImagesPath);
            defaultImagesPath = defaultImagesPathInfo.FullName;

            var defaultFieldImagesPathInfo = new DirectoryInfo(rd.DefaultFieldImagesPath);
            defaultFieldImagesPath = defaultFieldImagesPathInfo.FullName;

            var fieldElements = new List<IFieldUIElement>();

            #region 默认属性
            var defPageBackground = BrushManager.GetBrush(rd.DefaultPageBackground);
            if (defPageBackground == null)
                defPageBackground = System.Windows.Media.Brushes.White;

            var defBackground = BrushManager.GetBrush(rd.DefaultBackground);
            if (defBackground == null)
                defBackground = System.Windows.Media.Brushes.White;

            var defBoxBackground = BrushManager.GetBrush(rd.DefaultBoxBackground);  // 外框部件专用默认背景色
            if (defBoxBackground == null)
                defBoxBackground = System.Windows.Media.Brushes.Transparent;

            var defForeground = BrushManager.GetBrush(rd.DefaultForeground);
            if (defForeground == null)
                defForeground = System.Windows.Media.Brushes.Black;

            var defLineColor = BrushManager.GetBrush(rd.DefaultLineColor);
            if (defLineColor == null)
                defLineColor = System.Windows.Media.Brushes.Black;

            var defLineWidth = rd.DefaultLineWidth;

            var defLineDashType = MiniReportEditor.GetDashStyle(rd.DefaultLineDashType);
            if (defLineDashType == null)
                defLineDashType = DashStyles.Solid.Dashes;

            var defBoxColor = BrushManager.GetBrush(rd.DefaultBoxLineColor);
            if (defBoxColor == null)
                defBoxColor = System.Windows.Media.Brushes.Black;

            var defBoxLineWidth = rd.DefaultBoxLineWidth;

            var defBoxDashType = MiniReportEditor.GetDashStyle(rd.DefaultBoxLineDashType);
            if (defBoxDashType == null)
                defBoxDashType = DashStyles.Solid.Dashes;

            errForeColor = BrushManager.GetBrush(rd.ErrorMessageForeground);
            if (errForeColor == null)
            {
                errForeColor = System.Windows.Media.Brushes.Red;
            }
            #endregion

            for (var pageIndex = 0; pageIndex < rd.Pages.Count; pageIndex++)
            {
                var page = rd.Pages[pageIndex];
                var pc = new PageContent();
                var size = page.PageSize;
                pc.Width = size.Width;
                pc.Height = size.Height;

                #region 根据上/上/左/右四边边距和辅助线宽，计算出最大行、列数目并提供警告信息
                var curRowsCount = page.PageRowsCount;
                var curColumnsCount = page.PageColumnsCount;
                var leftMargin = page.LeftMargin;
                var rightMargin = page.RightMargin;
                var topMargin = page.TopMargin;
                var bottomMargin = page.BottomMargin;
                var assistLineWidth = rd.AssistLinesWidth;

                var hSpace = size.Width - leftMargin - rightMargin;
                var maxColumnsCount = (int)hSpace / (assistLineWidth + 10);
                var vSpace = size.Height - topMargin - rightMargin;
                var maxRowsCount = (int)vSpace / (assistLineWidth + 20);

                if (curRowsCount > maxRowsCount)
                {
                    innerWarningMsg.Append($"根据当前页面上下边距和辅助线宽度计算，第 {pageIndex + 1} 页最好不要超过 {maxRowsCount} 行。当前设置的是 {curRowsCount} 行，可能导致页面拥挤、错位。");
                }

                if (curColumnsCount > maxColumnsCount)
                {
                    innerWarningMsg.Append($"根据当前页面左右边距和辅助线宽度计算，第 {pageIndex + 1} 页最好不要超过 {maxColumnsCount} 列。当前设置的是 {curColumnsCount} 列，可能导致页面拥挤、错位。");
                }
                #endregion

                page.RefreshLocation(rd.AssistLinesWidth);

                var fixedPage = new FixedPage() { Width = size.Width, Height = size.Height, };

                // 向 fixedPage 中添加内容
                var mainCanvas = new Canvas()
                {
                    Width = size.Width,
                    Height = size.Height,
                    // 背景色后面会设置
                };
                fixedPage.Children.Add(mainCanvas);

                // mainCanvas 承载所有内容

                var pageBackgroundBrush = BrushManager.GetBrush(page.PageBackground);
                if (pageBackgroundBrush != null)
                    mainCanvas.Background = pageBackgroundBrush;
                else mainCanvas.Background = defPageBackground;

                if (drawAssistLines)  // 绘制辅助线
                {
                    var assistLinesBrush = BrushManager.GetBrush(rd.AssistLinesColor);
                    if (assistLinesBrush == null)
                    {
                        assistLinesBrush = System.Windows.Media.Brushes.SkyBlue;
                    }

                    var assistLinesWidth = rd.AssistLinesWidth;  // 辅助线宽度至少为 1
                    var assistDashArray = MiniReportEditor.GetDashStyle(rd.AssistLinesType);
                    if (assistDashArray == null)
                        assistDashArray = DashStyles.Solid.Dashes;   // 未设置视为实线（辅助线型不允许为空，但标记可能为空）

                    var outboxOfPage = new System.Windows.Shapes.Rectangle()
                    {
                        Width = page.ActualContentWidth + assistLinesWidth * 2 - assistLinesWidth,
                        Height = page.ActualContentHeight + assistLinesWidth * 2 - assistLinesWidth,
                        Stroke = assistLinesBrush,
                        StrokeThickness = assistLinesWidth,
                        StrokeDashArray = assistDashArray,
                        StrokeEndLineCap = PenLineCap.Flat,
                        StrokeStartLineCap = PenLineCap.Flat,
                        StrokeLineJoin = PenLineJoin.Miter,
                        StrokeDashCap = PenLineCap.Square,      // 会影响点、划线(应为Square)
                        SnapsToDevicePixels = true,
                    };
                    mainCanvas.Children.Add(outboxOfPage);
                    Canvas.SetZIndex(outboxOfPage, MiniReportEditor.AssistLineZIndex);                // 辅助线、框均在底层。
                                                                                                      // 层级关系到内容部件能否“覆盖”掉辅助线、装饰线条部件等。
                    Canvas.SetLeft(outboxOfPage, page.LeftTopPoint.X);
                    Canvas.SetTop(outboxOfPage, page.LeftTopPoint.Y);

                    for (int i = 0; i < page.PageColumnsCount - 1; i++)
                    {
                        // 竖线
                        var x = page.LeftTopPoint.X + (page.CellWidth + assistLinesWidth) * (i + 1);
                        var y1 = page.LeftTopPoint.Y + rd.AssistLinesWidth;
                        var y2 = page.LeftTopPoint.Y + page.PageRowsCount * (page.CellHeight + rd.AssistLinesWidth);

                        var line = new System.Windows.Shapes.Line()          // WPF Line 对象的坐标很奇怪，不如用 Rectangle 代替！
                        {
                            //Width = assistLinesWidth,
                            //Height = page.RightBottomPoint.Y - page.LeftTopPoint.Y + assistLinesWidth,
                            Y1 = y1,
                            Y2 = y2,
                            Stroke = assistLinesBrush,
                            StrokeThickness = assistLinesWidth,
                            StrokeDashArray = assistDashArray,
                            StrokeEndLineCap = PenLineCap.Flat,
                            StrokeStartLineCap = PenLineCap.Flat,
                            StrokeLineJoin = PenLineJoin.Miter,
                            StrokeDashCap = PenLineCap.Square,      // 会影响点、划线(应为Square)
                            SnapsToDevicePixels = true,
                        };

                        if (assistLinesWidth % 2 == 1)
                        {
                            line.X2 = line.X1 = x + assistLinesWidth / 2 + 0.5;
                        }
                        else
                        {
                            line.X2 = line.X1 = x + assistLinesWidth / 2;
                        }

                        mainCanvas.Children.Add(line);
                        //Canvas.SetLeft(line, x);
                        //Canvas.SetTop(line, page.LeftTopPoint.Y);
                        Canvas.SetZIndex(line, MiniReportEditor.AssistLineZIndex);           // 辅助线在底层
                    }

                    for (int i = 0; i < page.PageRowsCount - 1; i++)
                    {
                        // 横线
                        var y = page.LeftTopPoint.Y + (page.CellHeight + assistLinesWidth) * (i + 1);
                        var x1 = page.LeftTopPoint.X + rd.AssistLinesWidth;
                        var x2 = page.LeftTopPoint.X + page.PageColumnsCount * (page.CellWidth + rd.AssistLinesWidth);

                        var line = new System.Windows.Shapes.Line()          // WPF Line 对象的坐标很奇怪，不如用 Rectangle 代替！
                        {
                            //Height = assistLinesWidth,
                            //Width = page.RightBottomPoint.X - page.LeftTopPoint.X,
                            X1 = x1,
                            X2 = x2,
                            Stroke = assistLinesBrush,
                            StrokeThickness = assistLinesWidth,
                            StrokeDashArray = assistDashArray,
                            StrokeEndLineCap = PenLineCap.Flat,
                            StrokeStartLineCap = PenLineCap.Flat,
                            StrokeLineJoin = PenLineJoin.Miter,
                            StrokeDashCap = PenLineCap.Square,      // 会影响点、划线(应为Square)
                            SnapsToDevicePixels = true,
                        };

                        if (assistLinesWidth % 2 == 1)
                        {
                            line.Y2 = line.Y1 = y + assistLinesWidth / 2 + 0.5;
                        }
                        else
                        {
                            line.Y2 = line.Y1 = y + assistLinesWidth / 2;
                        }

                        mainCanvas.Children.Add(line);
                        //Canvas.SetLeft(line, page.LeftTopPoint.X + rd.AssistLinesWidth);
                        //Canvas.SetTop(line, y);
                        Canvas.SetZIndex(line, MiniReportEditor.AssistLineZIndex);           // 辅助线在底层
                    }
                }

                MiniReportEditor.BuildWidgets(groupIndex, rowsCount, rd, fieldElements, defBackground, 
                                              defBoxBackground, defForeground, defLineColor,
                                              defLineDashType, defBoxColor, defBoxDashType,
                                              defaultImagesPath, defaultFieldImagesPath,
                                              warningMsg, pageIndex, page, mainCanvas, rd.Widgets,
                                              out string idWidgetAreasText_inBar,                // 考试号填涂区域位置信息，此场景下实际会被忽略
                                              out string questionWidgetAreasText_inBar,          // 试题答案填涂区域位置信息，此场景下实际会被忽略
                                              out string answerSheetBoxBorderWidthRateText_inBar,
                                              out string answerSheetBoxBorderHeightRateText_inBar);   // 边四栏重复部件。

                MiniReportEditor.BuildWidgets(groupIndex, rowsCount, rd, fieldElements, defBackground,
                                              defBoxBackground, defForeground, defLineColor,
                                              defLineDashType, defBoxColor, defBoxDashType,
                                              defaultImagesPath, defaultFieldImagesPath,
                                              warningMsg, pageIndex, page, mainCanvas, page.Widgets,
                                              out string idWidgetAreasText,                // 考试号填涂区域位置信息，此场景下实际会被忽略
                                              out string questionWidgetAreasText,          // 试题答案填涂区域位置信息，此场景下实际会被忽略
                                              out string answerSheetBoxBorderWidthRateText,
                                              out string answerSheetBoxBorderHeightRateText);   // 只在单个页面中出现的部件

                ((IAddChild)pc).AddChild(fixedPage);
                fixedDocument.Pages.Add(pc);
                mainCanvas.InvalidateVisual();
            }

            return fieldElements;
        }

        private static void 填充记录行(文字表 dataContext, int dataGridItemIndex, List<IFieldUIElement> fieldUiElements,
                                       string defaultImagesPath, string defaultFieldImagesPath, System.Windows.Media.Brush errForeColor)
        {
            if (dataContext == null || dataContext.文字表体行集 == null || dataContext.文字表体行集.Count <= 0) return;

            if (dataGridItemIndex < 0 || dataGridItemIndex >= dataContext.文字表体行集.Count) return;

            var datarow = dataContext.文字表体行集[dataGridItemIndex];
            if (datarow == null) return;

            if (dataContext.文字表头行集 != null && dataContext.文字表头行集.Count > 0 &&
                dataContext.文字表头行集[0].文字表单元格集 != null &&
                dataContext.文字表头行集[0].文字表单元格集.Count > 0)
            {
                var headRow = dataContext.文字表头行集[0];

                if (errForeColor == null)
                    errForeColor = System.Windows.Media.Brushes.Red;

                if (dataContext.文字表体行集 != null && dataContext.文字表体行集.Count > 0)
                {
                    // 两层循环
                    foreach (var ui in fieldUiElements)
                    {
                        var hasFieldValue = false;
                        var compositeFields = MiniReportEditor.GetCompositeFieldInfos(ui.FieldName);

                        if (compositeFields == null)
                        {
                            // 为部件设置的是单字段名
                            for (int i = 0; i < headRow.文字表单元格集.Count; i++)
                            {
                                var headValue = headRow.文字表单元格集[i].文字表单元格文本.Trim().ToLower();
                                if (string.IsNullOrWhiteSpace(headValue)) continue;

                                var cellValue = datarow.文字表单元格集[i].文字表单元格文本;

                                if (string.IsNullOrWhiteSpace(ui.FieldName)) continue;

                                if (headValue == ui.FieldName.Trim().ToLower())
                                {
                                    ui.SetFieldValue(cellValue, defaultFieldImagesPath);
                                    hasFieldValue = true;
                                }
                            }
                        }
                        else
                        {
                            // 为部件设置的是复合字段名
                            var sb = new StringBuilder();

                            var trueValueParttern = ReporterDefinition.InnerTrueValuesText;
                            if (string.IsNullOrWhiteSpace(ReporterDefinition.DefaultTrueValuesText) == false)
                            {
                                trueValueParttern += ReporterDefinition.DefaultTrueValuesText;
                            }

                            var falseValueParttern = ReporterDefinition.InnerFalseValuesText;
                            if (string.IsNullOrWhiteSpace(ReporterDefinition.DefaultFalseValuesText) == false)
                            {
                                falseValueParttern += ReporterDefinition.DefaultFalseValuesText;
                            }

                            foreach (var cField in compositeFields)
                            {
                                var cFieldTxt = cField.Trim();
                                if ((cFieldTxt.StartsWith("\"") || cFieldTxt.StartsWith("“")) &&
                                   (cFieldTxt.EndsWith("\"") || cFieldTxt.EndsWith("”")))
                                {
                                    sb.Append(cFieldTxt.Substring(1, cFieldTxt.Length - 2)
                                                       .Replace("<!--半角逗号-->", ",").Replace("<!--全角逗号-->", "，")
                                                       .Replace("<!--半角双引号-->", "\"").Replace("<!--全角左双引号-->", "“").Replace("<!--全角右双引号-->", "”")
                                                       .Replace("<!--半角左花括号-->", "{").Replace("<!--全角左花括号-->", "｛")
                                                       .Replace("<!--半角右花括号-->", "}").Replace("<!--全角右花括号-->", "｝")  // 复合字段需要对这些字符进行转义
                                                       .Replace("<!--半角左方括号-->", "[").Replace("<!--全角左方括号-->", "［")  // 方括号准备用来转换逻辑值为（■是 □否）这样的样式
                                                       .Replace("<!--半角右方括号-->", "]").Replace("<!--全角右方括号-->", "］")
                                                       .Replace("<!--实心左方括号-->", "【").Replace("<!--实心右方括号-->", "】")
                                                       .Replace("<!--半角左圆括号-->", "(").Replace("<!--全角左圆括号-->", "（")  // 圆括号暂时未使用 2025.5.18
                                                       .Replace("<!--半角右圆括号-->", ")").Replace("<!--全角右圆括号-->", "）")

                                                       );  // 这里不用 Trim()，目的是保留可能需要的引号。
                                    continue;
                                }

                                for (int i = 0; i < headRow.文字表单元格集.Count; i++)
                                {
                                    var headValue = headRow.文字表单元格集[i].文字表单元格文本.Trim().ToLower();
                                    if (string.IsNullOrWhiteSpace(headValue)) continue;

                                    var cellValue = datarow.文字表单元格集[i].文字表单元格文本;

                                    if (string.IsNullOrWhiteSpace(ui.FieldName)) continue;


                                    // 这时是动态字段
                                    var matchCheckBoxWithFieldName = MiniReportEditor.RegCheckBoxWithFieldName.Match(cFieldTxt);
                                    if (matchCheckBoxWithFieldName.Success)
                                    {
                                        var fieldTail = cFieldTxt.Substring(matchCheckBoxWithFieldName.Length).Trim();
                                        if (headValue == fieldTail.ToLower())
                                        {
                                            var tfValues = matchCheckBoxWithFieldName.Value.Trim(new char[] { ' ', '　', '\t', '[', '［', '【', ']', '］', '】' })
                                                                                     .Split(new char[] { '|', '｜' }, StringSplitOptions.RemoveEmptyEntries);
                                            var trueValue = "";
                                            var falseValue = "";
                                            if (tfValues != null && tfValues.Length == 2)
                                            {
                                                trueValue += tfValues[0];
                                                falseValue += tfValues[1];
                                            }

                                            if (string.IsNullOrWhiteSpace(cellValue))
                                            {
                                                // 空值不显示
                                                //sb.Append("");
                                                hasFieldValue = true;
                                                continue;
                                            }

                                            if (trueValueParttern.Contains(cellValue.Trim().ToLower()))
                                            {
                                                // 真值
                                                sb.Append("■" + (string.IsNullOrWhiteSpace(trueValue) ? fieldTail : trueValue));
                                                hasFieldValue = true;
                                                continue;
                                            }

                                            if (falseValueParttern.Contains(cellValue.Trim().ToLower()))
                                            {
                                                // 假值
                                                sb.Append("□" + (string.IsNullOrWhiteSpace(falseValue) ? fieldTail : falseValue));
                                                hasFieldValue = true;
                                                continue;
                                            }

                                            sb.Append("Err: " + fieldTail);  // 不能识别的
                                        }
                                    }
                                    else
                                    {
                                        var matchCheckBoxWithBoolValue = MiniReportEditor.RegCheckBoxWithBoolValue.Match(cFieldTxt);
                                        if (matchCheckBoxWithBoolValue.Success)
                                        {
                                            if (headValue == cFieldTxt.Trim(new char[] { ' ', '　', '\t', '[', '［', '【', ']', '］', '】' }).ToLower())
                                            {
                                                if (trueValueParttern.Contains(cellValue.Trim().ToLower()))
                                                {
                                                    // 真值
                                                    sb.Append("■是　□否");
                                                    hasFieldValue = true;
                                                    continue;
                                                }

                                                if (falseValueParttern.Contains(cellValue.Trim().ToLower()))
                                                {
                                                    // 假值
                                                    sb.Append("□是　■否");
                                                    hasFieldValue = true;
                                                    continue;
                                                }

                                                sb.Append("Err: " + cellValue);  // 不能识别的
                                            }
                                        }
                                        else
                                        {
                                            if (headValue == cFieldTxt.Trim(new char[] { ' ', '　', '\t', '[', '［', '【', ']', '］', '】' }).ToLower())
                                            {
                                                sb.Append(cellValue);
                                                hasFieldValue = true;
                                            }
                                        }
                                    }
                                }
                            }

                            ui.SetFieldValue(sb.Replace("<br>", "\r\n").Replace("&#13;&#10;", "\r\n").Replace("<LineBreak/>", "\r\n").ToString(), defaultImagesPath);
                        }

                        if (hasFieldValue)
                        {
                            ui.RefreshErrorStatus();
                        }
                        else
                        {
                            ui.RefreshErrorStatus(errForeColor);
                        }
                    }
                }
            }
        }

        private static FixedPage 创建报表页面(int pageNum, string content)
        {
            FixedPage page = new FixedPage { /* 尺寸设置 */ };

            TextBlock text = new TextBlock
            {
                Text = $"Page {pageNum}: {content}",
                FontSize = 18
            };

            FixedPage.SetLeft(text, 100);
            FixedPage.SetTop(text, 100);
            page.Children.Add(text);

            return page;
        }
    }
}
